package com.bigfans.catalogservice.service.product;

import com.bigfans.catalogservice.dao.ProductDAO;
import com.bigfans.catalogservice.dao.ProductSpecDAO;
import com.bigfans.catalogservice.model.*;
import com.bigfans.catalogservice.service.sku.SkuService;
import com.bigfans.catalogservice.service.spec.SpecOptionService;
import com.bigfans.catalogservice.service.spec.SpecValueService;
import com.bigfans.framework.Applications;
import com.bigfans.framework.dao.BaseServiceImpl;
import com.bigfans.framework.event.ApplicationEventBus;
import com.bigfans.framework.model.SystemSetting;
import com.bigfans.framework.plugins.FileStoragePlugin;
import com.bigfans.framework.plugins.PluginManager;
import com.bigfans.framework.plugins.UploadResult;
import com.bigfans.framework.utils.CollectionUtils;
import com.bigfans.model.event.ProductCreatedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 商品服务类
 * 
 * @author lichong
 *
 */
@Service(ProductServiceImpl.BEAN_NAME)
public class ProductServiceImpl extends BaseServiceImpl<Product> implements ProductService {
	
	public static final String BEAN_NAME = "productService";
	
	@Autowired
	private SpecValueService specValueService;
	@Autowired
	private SpecOptionService specOptionService;
	@Autowired
	private SkuService skuService;
	@Autowired
	private ProductImageService productImageService;
	@Autowired
	private ProductSpecDAO productSpecDAO;

	@Autowired
	private ApplicationEventBus eventBus;
	@Autowired
	private FileStoragePlugin fileStoragePlugin;
	
	private ProductDAO productDAO;
	
	@Autowired
	public ProductServiceImpl(ProductDAO productDAO) {
		super(productDAO);
		this.productDAO = productDAO;
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<Product> listByCategory(String categoryId , Long start , Long pagesize) throws Exception{
		return productDAO.listByCategory(categoryId,start,pagesize);
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<Product> listByCategory(String[] categoryIdList , Long start , Long pagesize) throws Exception{
		return productDAO.listByCategory(categoryIdList,start,pagesize);
	}
	
	@Transactional
	public void create(Product prod , List<ProductImage> imgList , List<ProductSpec> specList) throws Exception {
		// 商品名字+规格值作为最终商品名
		StringBuilder nameBuilder = new StringBuilder(32);
		nameBuilder.append(prod.getName());
		specList.forEach((item) -> {
			nameBuilder.append(" ");
			nameBuilder.append(item.getValue());
		});
		prod.setName(nameBuilder.toString());
		
		// 创建商品
		super.create(prod);
		
		List<String> optionIds = new ArrayList<>();
		List<String> valueIds = new ArrayList<>();
		// 创建属性
		if(CollectionUtils.isNotEmpty(specList)){
			for (ProductSpec ps : specList) {
				ps.setProdId(prod.getId());
				String optionId = ps.getOptionId();
				String value = ps.getValue();
				SpecOption specOption = specOptionService.load(optionId);
				switch (specOption.getInputType()) {
				// 如果规格值是手动输入的,那么先创建规格值,传递过来的值为输入的内容
				case SpecOption.INPUTTYPE_MANUL:
					SpecValue sv = new SpecValue();
					sv.setCategoryId(prod.getCategoryId());
					sv.setOptionId(optionId);
					sv.setValue(value);
					specValueService.create(sv);
					ps.setValueId(sv.getId());
					break;
				// 如果是选择已存在的规格值,那么设置valueId,传递过来的值为选择的ID
				case SpecOption.INPUTTYPE_SELECT:
					ps.setValueId(value);
					break;
				default:
					break;
				}
				
				optionIds.add(ps.getOptionId());
				valueIds.add(ps.getValueId());
			}
			productSpecDAO.batchInsert(specList);
		}
		
		//创建SKU
		SKU sku = new SKU();
		sku.setPgId(prod.getPgId());
		sku.setProdId(prod.getId());
		sku.setStock(prod.getStock());
		sku.setOptKey(CollectionUtils.join(optionIds, SKU.KEYS_SEPARATOR));
		sku.setValKey(CollectionUtils.join(valueIds, SKU.KEYS_SEPARATOR));
		skuService.create(sku);
		
		// 创建图片
		if(imgList != null){
			for(int i = 0 ; i<imgList.size() ; i++){
				ProductImage pi = imgList.get(i);
				pi.setProdId(prod.getId());
				pi.setPgId(prod.getPgId());
				pi.setOrderNum(i + 1);
				String path = pi.getPath();
				File srcFile = null;
				try {
					srcFile = fileStoragePlugin.download(path);
					productImageService.upload(pi, srcFile);
				} catch (Exception e) {
					throw new RuntimeException("upload image error");
				} finally {
					if(srcFile != null){
						srcFile.deleteOnExit();
					}
					fileStoragePlugin.deleteFile(path);
				}
			}
		}
		
		// 更新缩略图
		ProductImage thumb = productImageService.getThumb(prod.getId());
		productDAO.updateThumb(prod.getId(), thumb.getPath());

		eventBus.publishEvent(new ProductCreatedEvent(prod.getId()));
	}

	@Transactional(readOnly = true)
	public Product getDetailById(String pid) throws Exception {
		Product product = super.load(pid);
		// 规格信息
		List<ProductSpec> specs = productSpecDAO.listByProdId(pid);
		product.setSpecList(specs);
		return product;
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<ProductSpec> listSpecsById(String pid) throws Exception {
		return productSpecDAO.listByProdId(pid);
	}

	/**
	 * 商品下架
	 * 
	 * @param productId
	 * @throws Exception 
	 */
	@Transactional
	public void unMarketable(String productId) throws Exception {
		Product productEntity = new Product();
		productEntity.setId(productId);
		productEntity.setIsOnSale(false);
		update(productEntity);
	}

	/**
	 * 商品上架
	 * 
	 * @param productId
	 * @throws Exception 
	 */
	@Transactional
	public void marketable(String productId) throws Exception {
		Product productEntity = new Product();
		productEntity.setId(productId);
		productEntity.setIsOnSale(true);
		update(productEntity);
	}
	
	@Override
	@Transactional
	public void updateHits(String prodId) throws Exception {
		productDAO.updateHits(prodId);
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<Product> listByPgId(String pgId) throws Exception {
		return productDAO.listByPgId(pgId);
	}

	@Override
	public UploadResult uploadImage(InputStream is, String imageExtension) throws Exception {
		SystemSetting setting = Applications.getSystemSetting();
		String imageServer = setting.getImageStoragePlugin();
		FileStoragePlugin storagePlugin = PluginManager.getFileStoragePlugin(imageServer);
		String key = "temp/images/itemservice/" + System.currentTimeMillis() +"_"+ UUID.randomUUID() + "." + imageExtension;
		UploadResult uploadResult = storagePlugin.uploadFile(is , key);
		return uploadResult;
	}
	
	@Override
	public UploadResult removeImage(String fileKey) throws Exception {
		SystemSetting setting = Applications.getSystemSetting();
		String imageServer = setting.getImageStoragePlugin();
		FileStoragePlugin storagePlugin = PluginManager.getFileStoragePlugin(imageServer);
		UploadResult uploadResult = storagePlugin.deleteFile(fileKey);
		return uploadResult;
	}

	@Transactional(readOnly = true)
	public List<Product> listHotSale(Long start , Long pagesize) throws Exception{
		return productDAO.listHotSale(start, pagesize);
	}

}
